﻿using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Windows.Media.Media3D;

namespace ImageTools
{
    internal class ImageGenCFileTool
    {
        private int PixelType { get; set; }
        private int IsDitherRgb565 { get; set; }
        private String OutFilesPath { get; set; }
        private int ArrayAlign { get; set; }
        private bool IsOutputCFile { get; set; }

        public ImageGenCFileTool(String outFilesPath, uint oType, int ditherMode, int align)
        {
            OutFilesPath = outFilesPath;
            ArrayAlign = align;
            PixelType = (int)oType;
            if (ditherMode == 0)
            {
                IsDitherRgb565 = 0;
            }
            else if (ditherMode == 1)
            {
                IsDitherRgb565 = 1;
            }

            IsOutputCFile = true;
        }
        
        public void ImageCreateCFile(String inFile)
        {
            byte[] rgbBuff = null;
            int width = 0, height = 0;

            if (PixelType == 1)
            {
                rgbBuff = ImageLoadFileToRGB888(inFile, ref width, ref height);
                if (rgbBuff == null)
                {
                    return;
                }

                ImageSaveCFile(ImageGetOutputPath(inFile)+".c", "Array_RGB888_"+ImageGetArrayName(inFile), rgbBuff, width, height);

                File.WriteAllBytes(ImageGetOutputPath(inFile) + ".bin", rgbBuff);
            }
            else if (PixelType == 2)
            {
                rgbBuff = ImageLoadFileToBGR888(inFile, ref width, ref height);
                if (rgbBuff == null)
                {
                    return;
                }

                ImageSaveCFile(ImageGetOutputPath(inFile) + ".c", "Array_BGR888_" + ImageGetArrayName(inFile), rgbBuff, width, height);

                File.WriteAllBytes(ImageGetOutputPath(inFile) + ".bin", rgbBuff);
            }
            else if (PixelType == 3)
            {
                rgbBuff = ImageLoadFileToRGB565(inFile, ref width, ref height);
                if (rgbBuff == null)
                {
                    return;
                }

                ImageSaveCFile(ImageGetOutputPath(inFile) + ".c", "Array_RGB565_" + ImageGetArrayName(inFile), rgbBuff, width, height);

                File.WriteAllBytes(ImageGetOutputPath(inFile) + ".bin", rgbBuff);
            }
            else if (PixelType == 4)
            {
                rgbBuff = ImageLoadFileToBGR565(inFile, ref width, ref height);
                if (rgbBuff == null)
                {
                    return;
                }

                ImageSaveCFile(ImageGetOutputPath(inFile) + ".c", "Array_BGR565_" + ImageGetArrayName(inFile), rgbBuff, width, height);

                File.WriteAllBytes(ImageGetOutputPath(inFile) + ".bin", rgbBuff);
            }
            else if (PixelType == 5)
            {
                rgbBuff = ImageLoadFileToNV12(inFile, ref width, ref height);
                if (rgbBuff == null)
                {
                    return;
                }

                ImageSaveCFile(ImageGetOutputPath(inFile) + ".c", "Array_NV12_" + ImageGetArrayName(inFile), rgbBuff, width, height);

                File.WriteAllBytes(ImageGetOutputPath(inFile) + ".bin", rgbBuff);
            }
            else if (PixelType == 6)
            {
                rgbBuff = ImageLoadFileToNV21(inFile, ref width, ref height);
                if (rgbBuff == null)
                {
                    return;
                }

                ImageSaveCFile(ImageGetOutputPath(inFile) + ".c", "Array_NV21_" + ImageGetArrayName(inFile), rgbBuff, width, height);

                File.WriteAllBytes(ImageGetOutputPath(inFile) + ".bin", rgbBuff);
            }
            else if (PixelType == 7)
            {
                rgbBuff = ImageLoadFileToNV16(inFile, ref width, ref height);
                if (rgbBuff == null)
                {
                    return;
                }

                ImageSaveCFile(ImageGetOutputPath(inFile) + ".c", "Array_NV16_" + ImageGetArrayName(inFile), rgbBuff, width, height);

                File.WriteAllBytes(ImageGetOutputPath(inFile) + ".bin", rgbBuff);
            }
            else if (PixelType == 8)
            {
                rgbBuff = ImageLoadFileToNV61(inFile, ref width, ref height);
                if (rgbBuff == null)
                {
                    return;
                }

                ImageSaveCFile(ImageGetOutputPath(inFile) + ".c", "Array_NV61_" + ImageGetArrayName(inFile), rgbBuff, width, height);

                File.WriteAllBytes(ImageGetOutputPath(inFile) + ".bin", rgbBuff);
            }
            else if (PixelType == 9)
            {
                rgbBuff = ImageLoadFileToYUYV(inFile, ref width, ref height);
                if (rgbBuff == null)
                {
                    return;
                }

                ImageSaveCFile(ImageGetOutputPath(inFile) + ".c", "Array_YUYV_" + ImageGetArrayName(inFile), rgbBuff, width, height);

                File.WriteAllBytes(ImageGetOutputPath(inFile) + ".bin", rgbBuff);
            }
            else if (PixelType == 10)
            {
                rgbBuff = ImageLoadFileToYVYU(inFile, ref width, ref height);
                if (rgbBuff == null)
                {
                    return;
                }

                ImageSaveCFile(ImageGetOutputPath(inFile) + ".c", "Array_YVYU_" + ImageGetArrayName(inFile), rgbBuff, width, height);

                File.WriteAllBytes(ImageGetOutputPath(inFile) + ".bin", rgbBuff);
            }
            else if (PixelType == 11)
            {
                rgbBuff = ImageLoadFileToUYVY(inFile, ref width, ref height);
                if (rgbBuff == null)
                {
                    return;
                }

                ImageSaveCFile(ImageGetOutputPath(inFile) + ".c", "Array_UYVY_" + ImageGetArrayName(inFile), rgbBuff, width, height);

                File.WriteAllBytes(ImageGetOutputPath(inFile) + ".bin", rgbBuff);
            }
            else if (PixelType == 12)
            {
                rgbBuff = ImageLoadFileToVYUY(inFile, ref width, ref height);
                if (rgbBuff == null)
                {
                    return;
                }

                ImageSaveCFile(ImageGetOutputPath(inFile) + ".c", "Array_VYUY_" + ImageGetArrayName(inFile), rgbBuff, width, height);

                File.WriteAllBytes(ImageGetOutputPath(inFile) + ".bin", rgbBuff);
            }
        }

        private string ImageGetOutputPath(String fileName)
        {
            string outfileName = Path.GetFileNameWithoutExtension(fileName);
            outfileName = Path.Combine(OutFilesPath, outfileName);

            return outfileName;
        }

        private string ImageGetArrayName(String fileName)
        {
            return Path.GetFileNameWithoutExtension(fileName);
        }

        

        public ImageGenCFileTool(String outFilesPath, uint oType, int ditherMode)
        {
            IsOutputCFile = false;
            OutFilesPath = outFilesPath;
            PixelType = (int)oType;
            if (ditherMode == 0)
            {
                IsDitherRgb565 = 0;
            }
            else if (ditherMode == 1)
            {
                IsDitherRgb565 = 1;
            }
            IsOutputCFile = false;
        }

        private void ImageSaveCFile(String filePath, string arrayName, byte[] buff, int width, int height)
        {
            if (buff == null || buff.Length == 0)
            {
                return;
            }

            var sb = new StringBuilder();

            sb.AppendFormat("// Image width = {0:D}, height = {1:D} \n", width, height);
            sb.AppendFormat("// Totle size = {0:D} bytes.\n", buff.Length);

            sb.AppendLine($"unsigned char {arrayName}[] = {{");
            sb.Append("    ");
            for (int i = 0; i < buff.Length; i++)
            {
                // 格式化每个字节为 0xXX 形式
                sb.AppendFormat("0x{0:X2}, ", buff[i]);

                // 换行处理
                if ((i + 1) % 32 == 0 && i != buff.Length - 1)
                    sb.AppendLine().Append("    ");
            }

            sb.AppendLine("\n};");

            File.WriteAllText(filePath, sb.ToString());
        }
        private byte[] ImageLoadFileToRGB888(String inFile, ref int width, ref int height, bool isAlign)
        {
            byte[] rgbBytes;
            int rgbLength;
            using (Image<Rgb24> image = Image.Load<Rgb24>(inFile))
            {
                width = image.Width;
                height = image.Height;

                if (isAlign)
                {
                    rgbLength = RoundUp(width * 3, ArrayAlign)  * height;
                }
                else
                {
                    rgbLength = width * height * 3;
                }

                rgbBytes = new byte[rgbLength];

                if (isAlign)
                {
                    int rowLength = RoundUp(width * 3, ArrayAlign);
                    int index = 0;
                    image.ProcessPixelRows(accessor =>
                    {
                        for (int y = 0; y < image.Height; y++)
                        {
                            Span<Rgb24> pixelRow = accessor.GetRowSpan(y); // 获取当前行的像素数据

                            for (int x = 0; x < image.Width; x++)
                            {
                                index = (y * rowLength + x);
                                Rgb24 pixel = pixelRow[x];
                                rgbBytes[index] = pixel.B;
                                rgbBytes[index + 1] = pixel.G;
                                rgbBytes[index + 2] = pixel.R;
                            }

                            // 填充剩余的0
                            for (int i = 0; i< (rowLength - image.Width * 3); i++)
                            {
                                rgbBytes[index + 3 + i] = 0;
                            }
                        }
                    });
                }
                else
                {
                    image.ProcessPixelRows(accessor =>
                    {
                        for (int y = 0; y < image.Height; y++)
                        {
                            Span<Rgb24> pixelRow = accessor.GetRowSpan(y);
                            for (int x = 0; x < image.Width; x++)
                            {
                                int index = (y * image.Width + x) * 3;
                                Rgb24 pixel = pixelRow[x];
                                rgbBytes[index] = pixel.B;
                                rgbBytes[index + 1] = pixel.G;
                                rgbBytes[index + 2] = pixel.R;
                            }
                        }
                    });
                }
            }

            return rgbBytes;
        }

        private byte[] ImageLoadFileToBGR888(String inFile, ref int width, ref int height)
        {
            byte[] rgbBytes;

            using (Image<Rgb24> image = Image.Load<Rgb24>(inFile))
            {
                width = image.Width;
                height = image.Height;
                rgbBytes = new byte[width * height * 3];

                image.ProcessPixelRows(accessor =>
                {
                    for (int y = 0; y < image.Height; y++)
                    {
                        Span<Rgb24> pixelRow = accessor.GetRowSpan(y);
                        for (int x = 0; x < image.Width; x++)
                        {
                            int index = (y * image.Width + x) * 3;
                            Rgb24 pixel = pixelRow[x];
                            rgbBytes[index] = pixel.R;
                            rgbBytes[index + 1] = pixel.G;
                            rgbBytes[index + 2] = pixel.B;
                        }
                    }
                });
            }

            return rgbBytes;
        }

        private byte[] ImageLoadFileToRGB565(String inFile, ref int width, ref int height)
        {
            byte[] rgbBytes;

            using (Image<Rgb24> image = Image.Load<Rgb24>(inFile))
            {
                width = image.Width;
                height = image.Height;
                rgbBytes = new byte[width * height * 2];

                image.ProcessPixelRows(accessor =>
                {
                    for (int y = 0; y < image.Height; y++)
                    {
                        Span<Rgb24> pixelRow = accessor.GetRowSpan(y);
                        for (int x = 0; x < image.Width; x++)
                        {
                            int index = (y * image.Width + x) * 2;
                            Rgb24 pixel = pixelRow[x];
                            rgbBytes[index] = (byte)((byte)(pixel.B >> 3) | (byte)(((pixel.G >> 2) & 0x07) << 5));
                            rgbBytes[index + 1] = (byte)(((pixel.R >> 3) << 5) | ((pixel.G >> 5)));
                        }
                    }
                });
            }

            return rgbBytes;
        }

        private byte[] ImageLoadFileToBGR565(String inFile, ref int width, ref int height)
        {
            byte[] rgbBytes;

            using (Image<Rgb24> image = Image.Load<Rgb24>(inFile))
            {
                width = image.Width;
                height = image.Height;
                rgbBytes = new byte[width * height * 2];

                image.ProcessPixelRows(accessor =>
                {
                    for (int y = 0; y < image.Height; y++)
                    {
                        Span<Rgb24> pixelRow = accessor.GetRowSpan(y);
                        for (int x = 0; x < image.Width; x++)
                        {
                            int index = (y * image.Width + x) * 2;
                            Rgb24 pixel = pixelRow[x];
                            rgbBytes[index] = (byte)((byte)(pixel.R >> 3) | (byte)(((pixel.G >> 2) & 0x07) << 5));
                            rgbBytes[index + 1] = (byte)(((pixel.B >> 3) << 5) | ((pixel.G >> 5)));
                        }
                    }
                });
            }

            return rgbBytes;
        }

        private byte[] ImageLoadFileToNV12(String inFile, ref int width, ref int height)
        {
            byte[] rgbBuff = ImageLoadFileToRGB888(inFile, ref width, ref height);

            if (rgbBuff == null || rgbBuff.Length == 0)
            {
                throw new Exception("Image Load to RGB888 Error.");
            }

            byte[] yuvBuff = Turbojpeg.JpegGenYUVFromRGB888(rgbBuff, width, height, 2);

            int y_size = Turbojpeg.tj3YUVPlaneSize(0, width, 0, height, 2);
            int u_size = Turbojpeg.tj3YUVPlaneSize(1, width, 0, height, 2);
            int v_size = Turbojpeg.tj3YUVPlaneSize(2, width, 0, height, 2);

            byte[] nv12Buff = new byte[yuvBuff.Length];

            // 拷贝所有的Y
            Array.Copy(yuvBuff, nv12Buff, y_size);

            for (int i = 0; i< u_size; i++)
            {
                nv12Buff[y_size + (i * 2)] = yuvBuff[y_size+i];
                nv12Buff[y_size + (i * 2) + 1] = yuvBuff[y_size + u_size + i];
            }
            
            return nv12Buff;
        }

        private byte[] ImageLoadFileToNV21(String inFile, ref int width, ref int height)
        {
            byte[] rgbBuff = ImageLoadFileToRGB888(inFile, ref width, ref height);

            if (rgbBuff == null || rgbBuff.Length == 0)
            {
                throw new Exception("Image Load to RGB888 Error.");
            }

            byte[] yuvBuff = Turbojpeg.JpegGenYUVFromRGB888(rgbBuff, width, height, 2);

            int y_size = Turbojpeg.tj3YUVPlaneSize(0, width, 0, height, 2);
            int u_size = Turbojpeg.tj3YUVPlaneSize(1, width, 0, height, 2);
            int v_size = Turbojpeg.tj3YUVPlaneSize(2, width, 0, height, 2);

            byte[] nv12Buff = new byte[yuvBuff.Length];

            // 拷贝所有的Y
            Array.Copy(yuvBuff, nv12Buff, y_size);

            for (int i = 0; i < u_size; i++)
            {
                nv12Buff[y_size + (i * 2)] = yuvBuff[y_size + u_size + i];  
                nv12Buff[y_size + (i * 2) + 1] = yuvBuff[y_size + i];
            }

            return nv12Buff;
        }

        private byte[] ImageLoadFileToNV16(String inFile, ref int width, ref int height)
        {
            byte[] rgbBuff = ImageLoadFileToRGB888(inFile, ref width, ref height);

            if (rgbBuff == null || rgbBuff.Length == 0)
            {
                throw new Exception("Image Load to RGB888 Error.");
            }

            byte[] yuvBuff = Turbojpeg.JpegGenYUVFromRGB888(rgbBuff, width, height, 1);

            int y_size = Turbojpeg.tj3YUVPlaneSize(0, width, 0, height, 1);
            int u_size = Turbojpeg.tj3YUVPlaneSize(1, width, 0, height, 1);
            int v_size = Turbojpeg.tj3YUVPlaneSize(2, width, 0, height, 1);

            byte[] nv16Buff = new byte[yuvBuff.Length];

            // 拷贝所有的Y
            Array.Copy(yuvBuff, nv16Buff, y_size);

            for (int i = 0; i < u_size; i++)
            {
                nv16Buff[y_size + (i * 2)] = yuvBuff[y_size + i];
                nv16Buff[y_size + (i * 2) + 1] = yuvBuff[y_size + u_size + i];
            }

            return nv16Buff;
        }

        private byte[] ImageLoadFileToNV61(String inFile, ref int width, ref int height)
        {
            byte[] rgbBuff = ImageLoadFileToRGB888(inFile, ref width, ref height);

            if (rgbBuff == null || rgbBuff.Length == 0)
            {
                throw new Exception("Image Load to RGB888 Error.");
            }

            byte[] yuvBuff = Turbojpeg.JpegGenYUVFromRGB888(rgbBuff, width, height, 1);

            int y_size = Turbojpeg.tj3YUVPlaneSize(0, width, 0, height, 1);
            int u_size = Turbojpeg.tj3YUVPlaneSize(1, width, 0, height, 1);
            int v_size = Turbojpeg.tj3YUVPlaneSize(2, width, 0, height, 1);

            byte[] nv16Buff = new byte[yuvBuff.Length];

            // 拷贝所有的Y
            Array.Copy(yuvBuff, nv16Buff, y_size);

            for (int i = 0; i < u_size; i++)
            {
                nv16Buff[y_size + (i * 2)] = yuvBuff[y_size + u_size + i];
                nv16Buff[y_size + (i * 2) + 1] = yuvBuff[y_size + i];
            }

            return nv16Buff;
        }

        private byte[] ImageLoadFileToYUYV(String inFile, ref int width, ref int height)
        {
            byte[] rgbBuff = ImageLoadFileToRGB888(inFile, ref width, ref height);

            if (rgbBuff == null || rgbBuff.Length == 0)
            {
                throw new Exception("Image Load to RGB888 Error.");
            }

            byte[] yuvBuff = Turbojpeg.JpegGenYUVFromRGB888(rgbBuff, width, height, 1);

            int y_size = Turbojpeg.tj3YUVPlaneSize(0, width, 0, height, 1);
            int u_size = Turbojpeg.tj3YUVPlaneSize(1, width, 0, height, 1);
            int v_size = Turbojpeg.tj3YUVPlaneSize(2, width, 0, height, 1);

            byte[] yuyvBuff = new byte[yuvBuff.Length];
            int width_t = width;
            int height_t = height;

            Parallel.For(0, height_t, y =>
            {
                int yOffset = y * width_t;              // 当前行 Y 平面的起始索引
                int uvOffset = y * (width_t / 2);       // 当前行 U/V 平面的起始索引
                int dstOffset = y * width_t * 2;        // 当前行 YUYV 的起始索引

                for (int x = 0; x < width_t; x += 2)
                {
                    // 获取 Y 分量
                    byte y0 = yuvBuff[yOffset + x];
                    byte y1 = yuvBuff[yOffset + x + 1];

                    // 获取 U/V 分量
                    byte u = yuvBuff[y_size + uvOffset + x / 2];
                    byte v = yuvBuff[y_size + u_size + uvOffset + x / 2];

                    // 填充 YUYV
                    yuyvBuff[dstOffset + x * 2] = y0;     // Y0
                    yuyvBuff[dstOffset + x * 2 + 1] = u;  // U
                    yuyvBuff[dstOffset + x * 2 + 2] = y1; // Y1
                    yuyvBuff[dstOffset + x * 2 + 3] = v;  // V
                }
            });

            return yuyvBuff;
        }

        private byte[] ImageLoadFileToYVYU(String inFile, ref int width, ref int height)
        {
            byte[] rgbBuff = ImageLoadFileToRGB888(inFile, ref width, ref height);

            if (rgbBuff == null || rgbBuff.Length == 0)
            {
                throw new Exception("Image Load to RGB888 Error.");
            }

            byte[] yuvBuff = Turbojpeg.JpegGenYUVFromRGB888(rgbBuff, width, height, 1);

            int y_size = Turbojpeg.tj3YUVPlaneSize(0, width, 0, height, 1);
            int u_size = Turbojpeg.tj3YUVPlaneSize(1, width, 0, height, 1);
            int v_size = Turbojpeg.tj3YUVPlaneSize(2, width, 0, height, 1);

            byte[] yuyvBuff = new byte[yuvBuff.Length];
            int width_t = width;
            int height_t = height;

            Parallel.For(0, height_t, y =>
            {
                int yOffset = y * width_t;              // 当前行 Y 平面的起始索引
                int uvOffset = y * (width_t / 2);       // 当前行 U/V 平面的起始索引
                int dstOffset = y * width_t * 2;        // 当前行 YUYV 的起始索引

                for (int x = 0; x < width_t; x += 2)
                {
                    // 获取 Y 分量
                    byte y0 = yuvBuff[yOffset + x];
                    byte y1 = yuvBuff[yOffset + x + 1];

                    // 获取 U/V 分量
                    byte u = yuvBuff[y_size + uvOffset + x / 2];
                    byte v = yuvBuff[y_size + u_size + uvOffset + x / 2];

                    // 填充 YUYV
                    yuyvBuff[dstOffset + x * 2] = y0;     // Y0
                    yuyvBuff[dstOffset + x * 2 + 1] = v;  // V
                    yuyvBuff[dstOffset + x * 2 + 2] = y1; // Y1
                    yuyvBuff[dstOffset + x * 2 + 3] = u;  // U
                }
            });

            return yuyvBuff;
        }

        private byte[] ImageLoadFileToUYVY(String inFile, ref int width, ref int height)
        {
            byte[] rgbBuff = ImageLoadFileToRGB888(inFile, ref width, ref height);

            if (rgbBuff == null || rgbBuff.Length == 0)
            {
                throw new Exception("Image Load to RGB888 Error.");
            }

            byte[] yuvBuff = Turbojpeg.JpegGenYUVFromRGB888(rgbBuff, width, height, 1);

            int y_size = Turbojpeg.tj3YUVPlaneSize(0, width, 0, height, 1);
            int u_size = Turbojpeg.tj3YUVPlaneSize(1, width, 0, height, 1);
            int v_size = Turbojpeg.tj3YUVPlaneSize(2, width, 0, height, 1);

            byte[] yuyvBuff = new byte[yuvBuff.Length];
            int width_t = width;
            int height_t = height;

            Parallel.For(0, height_t, y =>
            {
                int yOffset = y * width_t;              // 当前行 Y 平面的起始索引
                int uvOffset = y * (width_t / 2);       // 当前行 U/V 平面的起始索引
                int dstOffset = y * width_t * 2;        // 当前行 YUYV 的起始索引

                for (int x = 0; x < width_t; x += 2)
                {
                    // 获取 Y 分量
                    byte y0 = yuvBuff[yOffset + x];
                    byte y1 = yuvBuff[yOffset + x + 1];

                    // 获取 U/V 分量
                    byte u = yuvBuff[y_size + uvOffset + x / 2];
                    byte v = yuvBuff[y_size + u_size + uvOffset + x / 2];

                    // 填充 YUYV
                    yuyvBuff[dstOffset + x * 2] = u;  // U
                    yuyvBuff[dstOffset + x * 2 + 1] = y0;     // Y0
                    yuyvBuff[dstOffset + x * 2 + 2] = v;  // V
                    yuyvBuff[dstOffset + x * 2 + 3] = y1; // Y1
                }
            });

            return yuyvBuff;
        }

        private byte[] ImageLoadFileToVYUY(String inFile, ref int width, ref int height)
        {
            byte[] rgbBuff = ImageLoadFileToRGB888(inFile, ref width, ref height);

            if (rgbBuff == null || rgbBuff.Length == 0)
            {
                throw new Exception("Image Load to RGB888 Error.");
            }

            byte[] yuvBuff = Turbojpeg.JpegGenYUVFromRGB888(rgbBuff, width, height, 1);

            int y_size = Turbojpeg.tj3YUVPlaneSize(0, width, 0, height, 1);
            int u_size = Turbojpeg.tj3YUVPlaneSize(1, width, 0, height, 1);
            int v_size = Turbojpeg.tj3YUVPlaneSize(2, width, 0, height, 1);

            byte[] yuyvBuff = new byte[yuvBuff.Length];
            int width_t = width;
            int height_t = height;

            Parallel.For(0, height_t, y =>
            {
                int yOffset = y * width_t;              // 当前行 Y 平面的起始索引
                int uvOffset = y * (width_t / 2);       // 当前行 U/V 平面的起始索引
                int dstOffset = y * width_t * 2;        // 当前行 YUYV 的起始索引

                for (int x = 0; x < width_t; x += 2)
                {
                    // 获取 Y 分量
                    byte y0 = yuvBuff[yOffset + x];
                    byte y1 = yuvBuff[yOffset + x + 1];

                    // 获取 U/V 分量
                    byte u = yuvBuff[y_size + uvOffset + x / 2];
                    byte v = yuvBuff[y_size + u_size + uvOffset + x / 2];

                    // 填充 YUYV
                    yuyvBuff[dstOffset + x * 2] = v;  // V
                    yuyvBuff[dstOffset + x * 2 + 1] = y0;     // Y0
                    yuyvBuff[dstOffset + x * 2 + 2] = u;  // U
                    yuyvBuff[dstOffset + x * 2 + 3] = y1; // Y1
                }
            });

            return yuyvBuff;
        }

        private int RoundUp(int toRound, int num)
        {
            if (toRound % num == 0) return toRound;
            return (num - (toRound % num)) + toRound;
        }
    }
}
